<template>
    <el-upload
        action="#"
        :accept="fileAccept"
        :show-file-list="false"
        :auto-upload="false"
        :on-change="uploadAction"
        style="display: none;"
    >
        <div ref="uploadBtnRef"/>
    </el-upload>

    <Draggable
        v-model="files"
        filter=".forbid"
        item-key="id"
        animation="300"
        :sort="sort"
        :group="{ pull: 'clone', put: false }"
        @end="dragEnd"
        :move="dragMove"
        class="flex f-warp"
    >
        <template #item="{ element,index }">
            <div v-if="showUpload(element)">
                <div
                    v-if="element.isUpload"
                    class="f-c-c upload_btn--box upload_btn"
                    @click="beforeUploadAction"
                    :class="{ forbid: element.isUpload }"
                >
                    <el-icon class="upload_btn__icon" :size="iconSize">
                        <Plus/>
                    </el-icon>
                </div>
                <ul
                    v-else-if="element.error"
                    @click="uploadActionErrorAgain(index)"
                    class="f-c-c upload_btn--box upload_btn--error"
                >
                    <li class="upload_btn--error__li upload_btn--error__text">
                        <el-icon :size="20">
                            <WarningFilled/>
                        </el-icon>
                        <p>上传失败</p>
                        <p>{{ element.error }}</p>
                    </li>
                    <li class="upload_btn--error__li upload_btn--error__again">
                        <el-icon :size="20">
                            <Switch/>
                        </el-icon>
                        <p>重新上传</p>
                    </li>
                </ul>
            </div>
        </template>
    </Draggable>
</template>

<script setup lang="ts">
    import { ref, computed, onBeforeUnmount, watch, PropType } from "vue";
    import { Plus, RemoveFilled, ZoomIn, Switch, WarningFilled } from "@element-plus/icons-vue";
    import { useFormItem } from "element-plus";
    import Draggable from "vuedraggable";
    import { judgmentSizeError, judgmentExtError } from "@/components/globalUtils/UploadFile";
    import { _ossStore } from "@/store/config";

    const { formItem } = useFormItem();
    const validateChange = () => {
        formItem?.validate('change').catch(() => {
        })
    }

    const emit = defineEmits(['update:modelValue', 'change', 'upload', 'remove']);
    const props = defineProps({
        modelValue: {
            type: [String, Array]
        },
        action: {
            type: Boolean,
            default: false
        },
        // 隐藏删除按钮
        hideRemove: {
            type: Boolean,
            default: false
        },
        // 最大可上传数量
        limit: {
            type: Number,
            default: 1
        },
        // 文件类型 图片或视频 默认图片
        fileType: {
            type: String,
            default: 'image'
        },
        // 图片id唯一标识
        imageKey: {
            type: String,
            default: ''
        },
        // 文件大小
        size: {
            type: Number,
            default: 2
        },
        // 排序 默认禁止
        sort: {
            type: Boolean,
            default: false
        },
        iconSize: {
            type: String,
            default: '24'
        },
    });
    const isImage = computed(() => {
        return props.fileType === 'image';
    });
    const isVideo = computed(() => {
        return props.fileType === 'video';
    });
    // 只显示可选择文件类型
    const fileAccept = computed(() => {
        if (isVideo.value) {
            return _ossStore.videoAccept;
        } else {
            return _ossStore.imageAccept;
        }
    });
    // 判断文件类型
    const fileAcceptRule = computed(() => {
        if (isVideo.value) {
            return _ossStore.videoTypeRule;
        } else {
            return _ossStore.imageTypeRule;
        }
    });


    let uploadFileId: number = 1;// 列表id
    let propsLimit: number = props.limit as number;// 最大可上传数量
    let files = ref<ObjValueAny[]>([]);
    // 文件默认数据
    const defaultFiles = () => {
        files.value = [{ isUpload: true, id: uploadFileId++ }];
    };
    defaultFiles();
    // 已上传的数量
    const filesLen = computed(() => {
        return files.value.length - 1;
    });
    // 显示组件条件（已上传数量小于最大可上传数量）
    const showUpload = (element: ObjValueAny) => {
        return (isImage.value || isVideo.value) && ((filesLen.value < propsLimit && element.isUpload) || showProcess(element) || element.value);
    }
    // 显示上传进度
    const showProcess = (element: ObjValueAny) => {
        return uploadFileProcess.value[element.uid] || uploadFileProcess.value[element.uid] === 0;
    }
    // hover 预览图片
    const previewImageAsync = (id: number) => {
        (document.getElementById(`${props.imageKey || props.fileType}-${id}`) as any).click();
    }
    // 图片预览列表
    const previewFiles = computed(() => {
        let filterFiles = files.value.filter((row: ObjValueAny) => !!row.value);
        return filterFiles.map((row: ObjValueAny) => row.value);
    });
    // 预览图片下标
    const previewIndex = ref<number>(0);
    const handlePictureCardPreview = (row: ObjValueAny) => {
        previewIndex.value = files.value.findIndex((ele: ObjValueAny) => ele.id === row.id); // 动态获取下标
    }

    // 结束拖拽
    const dragEnd = () => {

    };
    // 禁止拖拽到此区域
    const dragMove = (e: ObjValueAny) => {
        if (e.relatedContext.element.isUpload) return false
    };

    const uploadBtnRef = ref();
    const beforeUploadAction = () => {
        onClickUploadAction();
    }
    // 上传失败后 重新上传
    const uploadActionErrorAgain = (i: number) => {

    }
    // 触发选择图片
    const onClickUploadAction = () => {
        uploadBtnRef.value.click();
    }
    // 选择上传图片
    const uploadFileProcess = ref<ObjValueAny>({});// 上传进度
    const uploadFailUid: ObjValueAny = {};// 上传失败uid
    const uploadAction = async (option: ObjValueAny) => {
        const { raw } = option;
        const _uid = raw.uid.toString();
        uploadFileProcess.value[_uid] = 0;
        uploadFailUid[_uid] = 0;
        let filesValue: ObjValueAny = { uid: _uid, id: uploadFileId++, error: '' };
        for (let key in raw) {
            if (!filesValue.hasOwnProperty(key)) {
                filesValue[key] = raw[key];
            }
        }
        const sizeError = judgmentSizeError(raw, props.size as number);
        if (sizeError) {
            filesValue.error = `${isVideo.value ? '视频' : '图片'}过大`;
        }
        const extError = judgmentExtError(raw, fileAcceptRule.value as string);
        if (extError) {
            filesValue.error = extError;
        }
        emit('update:modelValue', 'https://osscdn.china-smartech.com/test/upload/5419cc84c4de8d5f1a6c8b4df16d583b.png');
        console.info(filesValue);
    }
</script>

<style scoped lang="scss">
    .upload_btn--box {
        width: 70px;
        height: 70px;
        border: 1px dashed var(--el-border-color);
        border-radius: 6px;
        cursor: pointer;
    }

    .upload_btn {
        /* 上传图片按钮图标*/
        &__icon {
            color: var(--el-border-color-darker);
        }

        &:hover {
            border-color: var(--el-color-primary);

            .upload_btn__icon {
                color: var(--el-color-primary);
            }
        }
    }
</style>